// lexer.rs
use pest::Parser;
use pest_derive::Parser;

use crate::tokens::{Token, TokenType};

#[derive(Parser)]
#[grammar = "lexer.pest"]
pub struct Lexer;

pub struct SysYLexer;

impl SysYLexer {
    pub fn tokenize(input: &str) -> Result<Vec<Token>, Box<dyn std::error::Error>> {
        let mut tokens = Vec::new();
        let mut errors = Vec::new();

        // eprintln!("=== RAW INPUT ===");
        // eprintln!("{:?}", input);
        // eprintln!("=================");

        // let mut pairs = SysYLexer::parse(Rule::tokens, input).unwrap();
        // let top = pairs.next().unwrap();
        // dump_pair(top, 0);

        let parse_result = Lexer::parse(Rule::program, input)?;

        if let Some(tokens_pair) = parse_result.into_iter().next() {
            for pair in tokens_pair.into_inner() {
                if pair.as_rule() == Rule::token {
                    let inner_pair = pair.into_inner().next().unwrap();
                    let token = Self::parse_token(inner_pair);
                    if token.token_type == TokenType::ErrorToken {
                        errors.push(token);
                    } else {
                        tokens.push(token);
                    }
                }
            }
        }

        // 如果有错误，输出所有错误并退出
        if errors.is_empty() {
            for token in &tokens {
                eprintln!("{}", token);
            }
        } else {
            for error in &errors {
                eprintln!("{}", error);
            }
        }

        Ok(tokens)
    }

    // fn parse_token(pair: pest::iterators::Pair<Rule>) -> Result<Token, Box<dyn std::error::Error>> {
    fn parse_token(pair: pest::iterators::Pair<Rule>) -> Token {
        let mut lexeme = pair.as_str().to_string();
        let line = pair.as_span().start_pos().line_col().0;

        let token_type = match pair.as_rule() {
            // 关键字
            Rule::Const => TokenType::Const,
            Rule::Int => TokenType::Int,
            Rule::Void => TokenType::Void,
            Rule::If => TokenType::If,
            Rule::Else => TokenType::Else,
            Rule::While => TokenType::While,
            Rule::Break => TokenType::Break,
            Rule::Continue => TokenType::Continue,
            Rule::Return => TokenType::Return,
            Rule::For => TokenType::For,

            // 运算符
            Rule::Plus => TokenType::Plus,
            Rule::Minus => TokenType::Minus,
            Rule::Mul => TokenType::Mul,
            Rule::Div => TokenType::Div,
            Rule::Mod => TokenType::Mod,
            Rule::Assign => TokenType::Assign,
            Rule::Eq => TokenType::Eq,
            Rule::Neq => TokenType::Neq,
            Rule::Lt => TokenType::Lt,
            Rule::Gt => TokenType::Gt,
            Rule::Le => TokenType::Le,
            Rule::Ge => TokenType::Ge,
            Rule::Not => TokenType::Not,
            Rule::And => TokenType::And,
            Rule::Or => TokenType::Or,

            // 标点符号
            Rule::LParen => TokenType::LParen,
            Rule::RParen => TokenType::RParen,
            Rule::LBrace => TokenType::LBrace,
            Rule::RBrace => TokenType::RBrace,
            Rule::LBrackt => TokenType::LBrackt,
            Rule::RBrackt => TokenType::RBrackt,
            Rule::Comma => TokenType::Comma,
            Rule::Semicolon => TokenType::Semicolon,

            // 标识符和常量
            Rule::identifier => TokenType::Identifier,
            Rule::integer_const => {
                lexeme = Self::parse_integer_constant(&lexeme);
                TokenType::IntegerConstant
            }

            // 错误 token
            Rule::error_token => TokenType::ErrorToken,

            _ => {
                lexeme = "Unexpected token rule for `{lexeme}`.".to_string();
                TokenType::ErrorToken
            }
        };

        Token {
            token_type,
            lexeme,
            line: line,
        }
    }

    fn parse_integer_constant(text: &str) -> String {
        // 处理十六进制
        if let Some(hex_text) = text.strip_prefix("0x").or_else(|| text.strip_prefix("0X")) {
            // 处理十六进制前缀但无数字的情况
            if hex_text.is_empty() {
                return "0".to_string();
            }
            return match i32::from_str_radix(hex_text, 16) {
                Ok(value) => value.to_string(),
                Err(e) => format!("Invalid hexadecimal format: {}", e),
            };
        }

        // 处理八进制（以0开头且长度>1）
        if text.starts_with('0') && text.len() > 1 {
            // 处理八进制前缀但无数字的情况
            if text.len() == 1 {
                return "0".to_string();
            }
            return match i32::from_str_radix(&text[1..], 8) {
                Ok(value) => value.to_string(),
                Err(e) => format!("Invalid octal format: {}", e),
            };
        }

        // 处理十进制
        return match text.parse::<i32>() {
            Ok(value) => value.to_string(),
            Err(e) => format!("Invalid decimal format: {}", e),
        };
    }
}

#[allow(dead_code)]
fn dump_pair(pair: pest::iterators::Pair<Rule>, indent: usize) {
    eprintln!(
        "{}{:?}: {:?}",
        " ".repeat(indent),
        pair.as_rule(),
        pair.as_str()
    );
    for inner in pair.into_inner() {
        dump_pair(inner, indent + 2);
    }
}
